package com.example.flowermall.service;

import com.alibaba.fastjson2.JSONObject;
import com.example.flowermall.domain.WechatRequest;
import com.example.flowermall.domain.WechatResponse;
import com.example.flowermall.domain.WxPay;
import com.example.flowermall.entity.*;
import com.example.flowermall.entity.wx.WechatConstants;
import com.example.flowermall.util.RedisUtil;
import com.example.flowermall.util.WechatPayV3Utils;
import com.example.flowermall.util.WechatSignUtils;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.ObjectUtils;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.*;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.security.AlgorithmParameters;
import java.security.Security;
import java.util.*;
import java.util.concurrent.TimeUnit;


@Slf4j
@Component
public class WxService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    //jsonObject 就是利用code 获取到的json对象

    @Autowired
    public WechatPayV3Utils wechatPayV3Utils;
    private final IOrderService orderService;
    private final MembersService membersService;
    private final IntegralProductService integralProductService;
    private final IProductService productService;
    private final IShoppingCartService cartService;
    private final RedisUtil redisUtil;
    private final IOrderItemService orderItemService;
    private final IUserService userService;
    private final InvitatonService invitatonService;
    @Value("${wxpay.notify}")
    private String notify;

    public WxService(IOrderService orderService, MembersService membersService, IntegralProductService integralProductService, IProductService productService, ICategoryService categoryService, IShoppingCartService cartService, RedisUtil redisUtil, IOrderItemService orderItemService, IUserService userService, InvitatonService invitatonService) {
        this.orderService = orderService;
        this.membersService = membersService;
        this.integralProductService = integralProductService;
        this.productService = productService;

        this.cartService = cartService;
        this.redisUtil = redisUtil;
        this.orderItemService = orderItemService;
        this.userService = userService;
        this.invitatonService = invitatonService;
    }

    public static JSONObject wxDecrypt(String encryptedData, String sessionKey, String iv) throws Exception {
        // 开始解密
       /* byte[] encryptedDataByte = Base64.getDecoder().decode(encryptedData);
        byte[] sessionKeyByte = Base64.getDecoder().decode(sessionKey);
        byte[] ivByte = Base64.getDecoder().decode(iv);

        try {
            // 创建AES解密器
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            SecretKeySpec skeySpec = new SecretKeySpec(sessionKeyByte, "AES");
            IvParameterSpec ivParameterSpec = new IvParameterSpec(ivByte);
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivParameterSpec);
            byte[] resultByte = cipher.doFinal(encryptedDataByte);

            // 解密后的数据转换为字符串
            return new String(resultByte, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
            throw new Exception("微信解密失败");
        }*/
        try {
            // 加密秘钥
            byte[] dataByte = Base64.getDecoder().decode(encryptedData);
            byte[] keyByte = Base64.getDecoder().decode(sessionKey);
            byte[] ivByte = Base64.getDecoder().decode(iv);

            // 如果密钥不足16位，那么就补足.  这个if 中的内容很重要
            int base = 16;
            if (keyByte.length % base != 0) {
                int groups = keyByte.length / base + 1;
                byte[] temp = new byte[groups * base];
                Arrays.fill(temp, (byte) 0);
                System.arraycopy(keyByte, 0, temp, 0, keyByte.length);
                keyByte = temp;
            }
            // 初始化
            Security.addProvider(new BouncyCastleProvider());
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding");
            SecretKeySpec spec = new SecretKeySpec(keyByte, "AES");
            AlgorithmParameters parameters = AlgorithmParameters.getInstance("AES");
            parameters.init(new IvParameterSpec(ivByte));
            cipher.init(Cipher.DECRYPT_MODE, spec, parameters); // 初始化
            // 被加密的数据

            byte[] resultByte = cipher.doFinal(dataByte);
            if (null != resultByte && resultByte.length > 0) {
                String result = new String(resultByte, StandardCharsets.UTF_8);
                log.info("解析微信加密数据==>{}", result);
                return JSONObject.parseObject(result);
            }
        } catch (BadPaddingException e) {
            log.error("解析微信加密数据失败", e);
            e.printStackTrace();
            throw new Exception("微信解密失败");
        }
        return null;


    }

    //生成随机用户名，数字和字母组成,
    public String getStringRandom(int length) {
        String substring = UUID.randomUUID().toString().replaceAll("-", "").substring(0, 32);
        return substring;
    }
    public static String generateNonceStr() {
        return UUID.randomUUID().toString().replace("-", "").substring(0, 32);
    }
    public static String mapToXml(Map<String, String> data) {
        StringBuilder xml = new StringBuilder("<xml>");

        // 遍历 Map，将每个键值对转为 XML 标签
        for (Map.Entry<String, String> entry : data.entrySet()) {
            xml.append("<").append(entry.getKey()).append(">");
            xml.append(entry.getValue());
            xml.append("</").append(entry.getKey()).append(">");
        }

        xml.append("</xml>");

        return xml.toString();
    }

    public static Map<String, String> xmlToMap(String xml) {
        Map<String, String> map = new HashMap<>();
        try {
            // 创建 DocumentBuilderFactory 对象
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 创建 DocumentBuilder 对象
            DocumentBuilder builder = factory.newDocumentBuilder();
            // 将输入的 XML 字符串转换为输入流
            InputStream inputStream = new ByteArrayInputStream(xml.getBytes("UTF-8"));
            // 解析 XML 输入流并得到 Document 对象
            Document document = builder.parse(inputStream);

            // 获取根节点
            Element root = document.getDocumentElement();
            // 获取所有子节点
            NodeList nodeList = root.getChildNodes();

            // 遍历节点列表
            for (int i = 0; i < nodeList.getLength(); i++) {
                Node node = nodeList.item(i);
                // 如果是元素节点（即 <xxx> 标签）
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    String nodeName = node.getNodeName();
                    String nodeValue = node.getTextContent();
                    // 将节点名和节点值放入 map
                    map.put(nodeName, nodeValue);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    public Result createWxOrder(WxPay wxPay) throws Exception {
        CreateOrder createOrder = new CreateOrder();
        createOrder.setRemarks("余额充值");
        createOrder.setDeliveryType(3);
        createOrder.setIsPay(0);
        createOrder.setIsIntegral(0);
        createOrder.setUserId(wxPay.getUserId());
        createOrder.setTotal(wxPay.getTotalAmount());
        Orders order = orderService.createOrder(createOrder);
        if(!ObjectUtils.isEmpty(order)){
            Map<String, String> m = new HashMap<>();
            BigDecimal totalAmount = wxPay.getTotalAmount();
            if (totalAmount != null && totalAmount.compareTo(BigDecimal.ZERO) > 0) {
                // 将金额从元转换为分
                long totalFeeInCents = totalAmount.multiply(new BigDecimal("100")).longValue();
                // 将 long 转换为字符串并设置到 map 中
                m.put("total_fee", String.valueOf(totalFeeInCents));
            } else {
                // 处理无效金额的情况
                m.put("total_fee", "0");
            }
            m.put("appid", WechatConstants.WECHAT_MP_APPID);
            m.put("openid", wxPay.getOpenId());
            m.put("mch_id", WechatConstants.WECHAT_MCH_ID);
            m.put("nonce_str", generateNonceStr());
            m.put("body", wxPay.getSubject());
            m.put("out_trade_no", order.getOrderId());
            m.put("spbill_create_ip", "127.0.0.1");
            m.put("notify_url", notify);
            m.put("trade_type", "JSAPI");  // 交易类型，JSAPI代表公众号支付
            m.put("sign", WechatSignUtils.sign(m,WechatConstants.WECHAT_MCH_SECRET_V3,"MD5"));

            String url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
            String xmlData = mapToXml(m); // 假设 mapToXml 是将 Map 转为 XML 的方法

            OkHttpClient client = new OkHttpClient();
            RequestBody body = RequestBody.create(xmlData, MediaType.parse("application/xml; charset=utf-8"));
            Request request = new Request.Builder()
                    .url(url)
                    .post(body)
                    .build();
            try (Response response = client.newCall(request).execute()) {
                Map<String, String> map = xmlToMap(response.body().string());
                if(map.get("return_msg").equals("OK")&&map.get("return_code").equals("SUCCESS")){
                    //返回给小程序拉起微信支付的参数
                    Map<String, String> result = new HashMap<>();
                    result.put("appId", WechatConstants.WECHAT_MP_APPID); //小程序appid
                    result.put("timeStamp", (new Date().getTime() / 1000) + ""); //时间戳
                    result.put("nonceStr", map.get("nonce_str")); //32位随机字符串
                    result.put("signType", "MD5"); //加密方式 固定RSA
                    result.put("package","prepay_id=" +map.get("prepay_id"));
                    result.put("paySign", WechatSignUtils.sign(result,WechatConstants.WECHAT_MCH_SECRET_V3,"MD5")); //签名
                    result.put("out_trade_no", order.getOrderId()); //商户订单号 此参数不是小程序拉起支付所需的参数 因此不参与签名
                    return Result.success(result);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return Result.error("唤起微信支付失败");

    }

    public Result integral(CreateOrder createOrder) {
        //String orderId = OrderIdUtil.createOrderId();
        //创建订单
        createOrder.setIsIntegral(1);
        Orders order = orderService.createOrder(createOrder);
        //积分发生改变、商品库存发生改变
        IntegralProduct integralProduct = integralProductService.queryById(createOrder.getProductId());
        integralProduct.setProductStock(integralProduct.getProductStock()- createOrder.getProdCount());
        integralProduct.setSoldNum(integralProduct.getSoldNum()+ createOrder.getProdCount());
        integralProductService.update(integralProduct);
        Members members = new Members();
        members.setUid(createOrder.getUserId());
        members.setOrderId(order.getOrderId());
        members.setAmount(-(integralProduct.getPrice()*createOrder.getProdCount()));
        members.setCreateTime(new Date());
        members.setType(2);
        membersService.insert(members);
        return Result.success();
    }

    public Result balance(CreateOrder createOrder) {
       // String orderId = OrderIdUtil.createOrderId();
        //余额发生改变、商品库存发生改变
        if(ObjectUtils.isEmpty(createOrder.getCartId())){
            //创建订单
            createOrder.setIsIntegral(0);
            Orders order = orderService.createOrder(createOrder);
            Product product = productService.getById(createOrder.getProductId());
            product.setSoldNum(product.getSoldNum()+createOrder.getProdCount());
            product.setProductStock(product.getProductStock()-createOrder.getProdCount());
            productService.updateById(product);
            rebate(order);
            Members members = new Members();
            members.setUid(createOrder.getUserId());
            members.setType(1);
            members.setOrderId(order.getOrderId());
            members.setAmount(-(product.getPrice().doubleValue()*createOrder.getProdCount()));
            members.setCreateTime(new Date());
            membersService.insert(members);
            /*//积分增加
            members.setType(2);
            members.setAmount((product.getPrice().doubleValue()*createOrder.getProdCount()));
            membersService.insert(members);*/
            return Result.success();
        }
        //创建订单
        createOrder.setIsIntegral(0);
        Orders order = orderService.createOrder(createOrder);
        List<OrderItem> orderItems = orderItemService.getByOrderId(order.getOrderId());
        for (OrderItem orderItem : orderItems) {
            Product product = productService.getById(orderItem.getProductId());
            product.setSoldNum(product.getSoldNum() + orderItem.getBuyCounts());
            product.setProductStock(product.getProductStock() - orderItem.getBuyCounts());
            productService.updateById(product);
            rebate(order);
            Members members = new Members();
            members.setUid(createOrder.getUserId());
            members.setType(1);
            members.setOrderId(order.getOrderId());
            members.setAmount(-(product.getPrice().doubleValue() * orderItem.getBuyCounts()));
            members.setCreateTime(new Date());
            membersService.insert(members);
            /*//积分增加
            members.setType(2);
            members.setAmount((product.getPrice().doubleValue() * orderItem.getBuyCounts()));
            membersService.insert(members);*/
        }
        return Result.success();
    }

    public ResponseEntity<WechatResponse> notifyWx(WechatRequest wechatRequest, HttpServletRequest request) throws IOException {
       /* BufferedReader br = new BufferedReader(new InputStreamReader((ServletInputStream) request.getInputStream()));
        String line = null;
        StringBuilder sb = new StringBuilder();
        while ((line = br.readLine()) != null) {
            sb.append(line);
        }
        br.close();
        //sb为微信返回的xml
        String notityXml = sb.toString();
        String resXml = "";
        System.out.println("接收到的报文：" + notityXml);
        Map<String, String> map = xmlToMap(notityXml);*/

        String resXml = "";
        String returnCode =wechatRequest.getReturnCode();
        if ("SUCCESS".equals(returnCode)) {
            String trade_no = wechatRequest.getOutTradeNo();
            Orders orders = orderService.getByOrderId(trade_no, 0);
            if("SUCCESS".equals(wechatRequest.getResultCode())){
                Object cacheObject = redisUtil.getCacheObject(trade_no);
                if(!ObjectUtils.isEmpty(cacheObject)){
                    System.out.println("===微信支付回调数据结束===");
                    return ResponseEntity.ok(new WechatResponse());
                }
                redisUtil.setCacheObject(trade_no,"1",5, TimeUnit.MINUTES);
                orders.setOrderStatus("5");
                orderService.updateOrder(orders);
                Members members = new Members();
                members.setUid(orders.getUserId());
                members.setType(1);
                members.setOrderId(trade_no);
                double price = orders.getTotalPrice().doubleValue();
                double integral = getIntegral(price);
                members.setAmount(integral);
                members.setCreateTime(new Date());
                membersService.insert(members);
            }
        } else {
             resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                    + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
        }
        System.out.println("微信支付回调数据结束");
        WechatResponse response = new WechatResponse();
        response.setReturnMsg("OK");
        response.setReturnCode("SUCCESS");
        return ResponseEntity.ok(response);
    }

    private double getIntegral(Double price){
         Map<Double,Double> integralMap = new HashMap<>();
         integralMap.put(500D,100D);
         integralMap.put(1000D,300D);
         integralMap.put(2000D,800D);
         return integralMap.get(price);
    }

    /**
     * 两层返利(直接推返利润15%，次推反利润10%)*/
    private void rebate(Orders order){
        double profit;
        double sum1 = 0;
        double sum2 = 0;
        List<OrderItem> orderItems = orderItemService.getByOrderId(order.getOrderId());
        //获取自己邀请人
        User user = userService.getInvitation(order.getUserId());
        if(!ObjectUtils.isEmpty(orderItems)&&!ObjectUtils.isEmpty(user)){
            for(OrderItem orderItem : orderItems){
                Product product = productService.getById(orderItem.getProductId());
                profit = product.getPrice().doubleValue()-product.getCostPrice();
                user.setRebate(user.getRebate()+profit*0.15);
                sum1 += profit*0.15;
                userService.updateUser(user);
                User userUsers = user.getUsers();
                userUsers.setRebate(userUsers.getRebate()+ profit*0.1);
                sum2 += profit*0.1;
                userService.updateUser(userUsers);
            }
            Invitaton invitaton = new Invitaton();
            invitaton.setUserId(user.getId());
            invitaton.setOrderId(order.getOrderId());
            invitaton.setRebate(sum1);
            invitatonService.insert(invitaton);
            invitaton.setUserId(user.getUsers().getId());
        }
    }
}
